﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text.RegularExpressions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Daan;
using DanMuGame;
using SuperSocket.ClientEngine;
using UnityEngine;

namespace DouyuDanmu
{
    public class DouyuDanmuClient : BaseDanmuClient
    {
        public int groupId = -9999;
        private bool running = true;

        protected DouyuClient client;

        private readonly string baseFaceUrl = "https://apic.douyucdn.cn/upload/{0}_middle.jpg";

        public async void Start()
        {
            Message.Get("DouyuDanmu").AddListener("DouyuJson", (object content) =>
            {
                this.HandleMessage((Dictionary<string, object>)content);
            });


            ThreadStart start = new ThreadStart(this.Test);
            Thread thread = new Thread(start);
            thread.Start();
            this.client = new DouyuClient((int)this.roomId, (Dictionary<string, object> json) =>
            {
                Message.Get("DouyuDanmu").SendMessage("DouyuJson", json);
            });

            await this.client.Connect();

            Debug.Log("连接上了斗鱼");
        }

        public void HandleMessage(Dictionary<string, object> json)
        {
            try
            {
                if (json.ContainsKey("type"))
                {
                    var type = json["type"];
                    // Debug.Log(type);
                    switch (type)
                    {
                        case "chatmsg":
                            this.DebugJson(json);
                            {
                                var uid = json.TryGet("uid").ToString();
                                var nickName = json.TryGet("nn").ToString();
                                var content = json.TryGet("txt").ToString();
                                var faceUrl = this.GetFaceUrl(json.TryGet("ic"));

                                this.DanmuMessageHandlerAsync(uid, nickName, content, faceUrl);
                            }
                            break;
                        case "dgb":
                            {
                                this.DebugJson(json);
                                var uid = json.TryGet("uid").ToString();
                                var nickName = json.TryGet("nn").ToString();
                                var faceUrl = this.GetFaceUrl(json.TryGet("ic"));
                                var giftId = long.Parse(json.TryGet("gfid").ToString());
                                var count = int.Parse(json.TryGet("gfcnt").ToString());

                                this.GiftMessageHandlerAsync(uid, nickName, faceUrl, "", giftId.ToString(), 1, count);
                            }
                            break;
                    }
                }
                else
                {
                    Debug.Log("没有Type的消息，看看是啥" + json);
                }
            }
            catch (System.Exception e)
            {
                Debug.LogError(e.StackTrace);
                throw e;
            }
        }



        string GetFaceUrl(object faceUrl)
        {
            return string.Format(baseFaceUrl, faceUrl.ToString());
        }

        void DebugJson(Dictionary<string, object> json)
        {
            if (!this.debugMessage) return;
            foreach (var item in json)
            {
                Debug.Log(item);
            }
        }

        public override void DanmuMessageHandlerAsync(string uid, string nickname, string content, string faceUrl)
        {
            var user = UserManager.Instance.UpdateUserInfo("Douyu", this.roomId, uid, nickname, faceUrl);
            //@这里要补充一个斗鱼的VIP转换
            UserManager.Instance.SetVip(user, 0);
            UserManager.Instance.UpdateActivePlayerList("Douyu", this.roomId, uid);

            DanmuCommandManager.Instance.ParseCommand(UserManager.Instance.GetUserKey(user.info), content);
        }

        public override void GiftMessageHandlerAsync(string uid, string nickname, string faceUrl, string giftName, string giftId, int giftPrice, int giftCount)
        {
            var user = UserManager.Instance.UpdateUserInfo("Douyu", this.roomId, uid, nickname, faceUrl);
            //@这里要补充一个斗鱼的VIP转换
            UserManager.Instance.SetVip(user, 0);
            UserManager.Instance.UpdateActivePlayerList("Douyu", this.roomId, uid);
            //@这里要补充一个斗鱼礼物表
            this.ParseGift(uid, giftId.ToString(), giftId, 100, 1);
        }
        
        public void Test()
        {
            int dwMrkl = Environment.TickCount;     // 记录执行的时间，因为斗鱼规定每45秒要向斗鱼发送一次心跳消息（否则踢下线）

            TcpClient tcpClient = new TcpClient();
            tcpClient.Connect("danmuproxy.douyu.com", 8601);

            //网络数据
            using (NetworkStream ms = tcpClient.GetStream())
            {
                ////登陆请求
                SocketHelper.LiveMessagePush(string.Format("type@=loginreq/roomid@={0}/\0", this.roomId), ms);

                //接收数据
                while (this.running /*&& tcpClient.Connected*/)
                {
                    if (!tcpClient.Connected)
                    {
                        tcpClient.Connect("danmuproxy.douyu.com", 8601);
                        //登陆请求
                        SocketHelper.LiveMessagePush(string.Format("type@=loginreq/roomid@={0}/\0", this.roomId), ms);
                    }

                    //发送心跳
                    if (!ms.DataAvailable && tcpClient.Connected)
                    {
                        // 不管是否有数据，只要SOCKET连接那么就进行心跳判断

                        if (Environment.TickCount - dwMrkl >= 45000)
                        {
                            dwMrkl = Environment.TickCount;                     // 重新计算心跳消息时间

                            SocketHelper.LiveMessagePush("type@=mrkl/\0", ms);
                        }

                        Thread.Sleep(5);
                        continue;
                    }

                    //发送心跳
                    if (Environment.TickCount - dwMrkl >= 45000)
                    {
                        dwMrkl = Environment.TickCount;

                        SocketHelper.LiveMessagePush("type@=mrkl/\0", ms);
                    }

                    byte[] buffer = new byte[SOCKET_PACKAGE.BufferSize];

                    ms.Read(buffer, 0, buffer.Length);

                    int dwLen = BitConverter.ToInt32(buffer, 0);

                    int unReadOfBytes = dwLen;

                    using (MemoryStream s = new MemoryStream())
                    {
                        // 大家都知道TCP有粘包数据，因为不是优雅的一问一答式，所以要自行处理，这是我想到的最简单处理粘包的办法咯
                        do
                        {
                            buffer = new byte[unReadOfBytes >= 1024 ? 1024 : unReadOfBytes];

                            int dwBytesOfRead = ms.Read(buffer, 0, buffer.Length);

                            s.Write(buffer, 0, dwBytesOfRead);

                            unReadOfBytes -= dwBytesOfRead;

                        } while (unReadOfBytes > 0);

                        s.Position = 0;

                        if (true)
                        {
                            string content = Encoding.UTF8.GetString(s.ToArray(), 8, dwLen - 8);

                            var strArray = Regex.Split(content, "/", RegexOptions.IgnoreCase);
                            var str2Array = Regex.Split(strArray[0], "@=", RegexOptions.IgnoreCase);

                            if (str2Array.Length > 1)
                            {
                                if (string.Compare("type", str2Array[0], true) == 0 && string.Compare("loginres", str2Array[1], true) == 0)
                                {
                                    // 当我们收到loginres消息后再发送加入房间分组消息
                                    SocketHelper.LiveMessagePush(string.Format("type@=joingroup/rid@={0}/gif@={1}/\0", this.roomId, this.groupId), ms);
                                }
                                else
                                {
                                    Message.SendMessage("DouYuDanMu", content, false);
                                    string message_type = str2Array[1].Replace("@S", "/").Replace("@A", "@");

                                    if (!string.IsNullOrWhiteSpace(message_type) && string.Compare("mrkl", message_type, true) != 0)
                                    {
                                        // 这里拿到的content数据就是不含心跳报文的数据，具体要怎么处理看你自己需求了
                                        // TO DO ：
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        private void OnApplicationQuit()
        {
            this.running = false;
        }
    }
}
